package org.easypool;

import lombok.Getter;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;

public final class PoolConnection implements InvocationHandler {

    private PoolDataSource poolDataSource;
    private Connection realConnection;
    private Connection proxyConnection;
    private boolean valid;

    private Long bornTimeMillis;

    private Class<?> [] Interfaces = {Connection.class};

    public PoolConnection(Connection realConnection,PoolDataSource poolDataSource) {
        this.valid = true;
        this.bornTimeMillis = System.currentTimeMillis();
        this.poolDataSource = poolDataSource;
        this.realConnection = realConnection;
        this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(),Interfaces,this);
    }

    @Getter
    private enum MethodEnum{
        CLOSE("close");
        private String name;
        MethodEnum(String name) { this.name = name; }
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //if call close method
        if (method.getName().equals(MethodEnum.CLOSE.getName())) {
           // recovery resource into idle pool
           this.setBornTimeMillis(System.currentTimeMillis());
           poolDataSource.pushConnection(this);
           return null;
        }

        Object invokeResult = method.invoke(this.realConnection, args);

        return invokeResult;
    }


    public boolean isValid() {
        return poolDataSource.pingConnection(this);
    }

    public Connection getProxyConnection() {
        return proxyConnection;
    }

    public Connection getRealConnection() {
        return realConnection;
    }

    public void invalidate() {
        valid = false;
    }

    public Long getBornTimeMillis() {
        return bornTimeMillis;
    }

    public void setBornTimeMillis(Long bornTimeMillis) {
        this.bornTimeMillis = bornTimeMillis;
    }
}
